package vb.week2.tabular;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import vb.week2.tabular.Token.Kind;

public class Parser
{

  protected Scanner scanner;
  protected Token currentToken;
  
  /**
   * @param args
   */
  public static void main(String[] args)
  {
    FileInputStream is = null;
    try
    {
      is = new FileInputStream(new File("sample-3.tex"));
    }
    catch (FileNotFoundException e)
    {
      e.printStackTrace();
    }
    Scanner scanner = new Scanner(is);
    Parser p = new Parser(scanner);
    System.out.println(p.parse());
  }

  /**
   * @param scanner
   *          the Scanner object to be used for parsing
   * @requires scanner != null;
   */
  public Parser(Scanner scanner)
  {
    this.scanner = scanner;
  }

  protected void accept(Kind expected) throws SyntaxErrorException
  {
    if (currentToken.getKind() == expected)
      currentToken = scanner.getToken();
    else
      throw new SyntaxErrorException(1+scanner.getCurrentLineNumber() + ": Expected kind: " + expected + ", found: "
          + currentToken.getKind() + ".");
  }

  protected void acceptIt() throws SyntaxErrorException
  {
    currentToken = scanner.getToken();
  }

  /**
   * Parses the input as LaTeX tabular specification.
   * 
   * @return {@code true} if parsing was successful
   */
  public boolean parse()
  {
    boolean result = true;
    try
    {
      currentToken = scanner.getToken();
      parseLatexTabular();
    }
    catch (SyntaxErrorException e)
    {
      System.err.println(e.getMessage());
      result = false;
    }
    if(currentToken.getKind() != Kind.EOT)
      result = false;
    
    return result;
  }

  protected void parseBeginTabular() throws SyntaxErrorException
  {
//    System.out.println("parsing begin tabular");
    accept(Kind.BSLASH);
    accept(Kind.BEGIN);
    accept(Kind.LCURLY);
    accept(Kind.TABULAR);
    accept(Kind.RCURLY);
  }

  protected void parseColsSpec() throws SyntaxErrorException
  {
//    System.out.println("parsing cols spec");
    accept(Kind.LCURLY);
    accept(Kind.IDENTIFIER);
    accept(Kind.RCURLY);
  }

  protected void parseEndTabular() throws SyntaxErrorException
  {
//    System.out.println("parsing end tabular");
    accept(Kind.BSLASH);
    accept(Kind.END);
    accept(Kind.LCURLY);
    accept(Kind.TABULAR);
    accept(Kind.RCURLY);
  }

  protected void parseEntries() throws SyntaxErrorException
  {
//    System.out.println("parsing entries");
    switch (currentToken.getKind())
    {
    case NUM:
    case IDENTIFIER:
      parseEntry();
      parseEntries();
      break;
    case AMPERSAND:
      acceptIt();
      parseEntry();
      parseEntries();
      break;
    case DOUBLE_BSLASH:
      break;
    }
  }

  protected void parseEntry() throws SyntaxErrorException
  {
//    System.out.println("parsing entry");
//    System.out.println(currentToken.getKind());
    switch (currentToken.getKind())
    {
    case NUM:
    case IDENTIFIER:
      acceptIt();
      break;
    case DOUBLE_BSLASH:
      break;
    case AMPERSAND:
      break;
    }
  }

  protected void parseLatexTabular() throws SyntaxErrorException
  {
//    System.out.println("parsing latex tabular");
    parseBeginTabular();
    parseColsSpec();
    parseRows();
    parseEndTabular();
  }

  protected void parseRows() throws SyntaxErrorException
  {
//    System.out.println("parsing rows");
    while (currentToken.getKind() != Kind.BSLASH)
    {
      parseEntries();
      accept(Kind.DOUBLE_BSLASH);
    }
  }
}
